package client

import (
	"errors"
	"feng-che.com/server/driver-quiz/myApp"
	serverCommon "fiberCommonUtils/common"
	request2 "fiberCommonUtils/request"
	"fmt"
	"github.com/gofiber/fiber/v2"
	"github.com/tidwall/gjson"
	"go.mongodb.org/mongo-driver/mongo"
	"io"
	"mongoDB"
	"net/http"
	"time"
)

type clientWxMPLoginUpload struct {
	Code string `json:"code"`
}

type clientInfoResponse struct {
	ID       string `json:"id"`
	Name     string `json:"name"`
	Nickname string `json:"nickName"`
	Phone    string `json:"phone"`
	Gender   string `json:"gender"`
	OpenId   string `json:"openId"`
	UnionId  string `json:"unionId"`
	Token    string `json:"token"`
	IsCoach  bool   `json:"isCoach"`
	Avatar   string `json:"avatar"`
}

func (receiver *clientInfoResponse) SchemaToResponse(client *Client) {
	receiver.ID = client.ID.Hex()
	receiver.Name = client.Information.Name
	receiver.Nickname = client.Information.Nickname
	receiver.Phone = client.Contact.Phone
	receiver.Gender = client.Information.Gender
	receiver.OpenId = client.AuthInfo.WxOpenID
	receiver.UnionId = client.AuthInfo.WxUnionID
	receiver.Avatar = client.Information.Photo
}

type WxMPLoginResponse struct {
	OpenId  string `json:"openId"`
	UnionId string `json:"unionId"`
}

func WxMPLogin(c *fiber.Ctx) error {
	data := request2.ParsePostLikeRequest(c, &clientWxMPLoginUpload{}).(*clientWxMPLoginUpload)
	if data.Code == "" {
		return fiber.NewError(500, "没有传入CODE")
	}
	url := fmt.Sprint(
		`https://api.weixin.qq.com/sns/jscode2session?appid=`,
		myApp.AppSetting.Wx.WxMpAppId,
		`&secret=`,
		myApp.AppSetting.Wx.WxMpAppSecret,
		`&js_code=`,
		data.Code,
		`&grant_type=authorization_code`)
	httpClient := new(http.Client)
	httpClient.Timeout = 20 * time.Second
	loginResp, err := httpClient.Get(url)
	if loginResp == nil {
		return fiber.NewError(500, "微信返回数据为nil")
	} else {
		defer loginResp.Body.Close()
	}
	body, err := io.ReadAll(loginResp.Body)
	if err != nil {
		return fiber.NewError(500, err.Error())
	}
	json := string(body)
	if gjson.Valid(json) == false {
		return fiber.NewError(500, "微信服务器返回数据不为json，格式错误")
	}
	errcode := gjson.Get(json, "errcode")
	//fmt.Println(string(body))
	if errcode.Num != 0 {
		return fiber.NewError(500, gjson.Get(json, "errmsg").Str)
	}
	if errcode.Str != "" {
		return fiber.NewError(500, "微信登录错误:"+errcode.Str)
	}
	//session_key := gjson.Get(json, "session_key").Str
	result := new(WxMPLoginResponse)
	result.OpenId = gjson.Get(json, "openid").Str
	result.UnionId = gjson.Get(json, "unionid").Str
	c.Locals("wxAuth", result)
	return c.Next()
}

func ResponseClientFound(c *fiber.Ctx) error {
	ctx, cancel := mongoDB.MongoDBTimeoutContext()
	defer cancel()
	auth := c.Locals("wxAuth").(*WxMPLoginResponse)
	_client := new(Client)
	_client.AuthInfo.WxOpenID = auth.OpenId
	_client.AuthInfo.WxUnionID = auth.UnionId
	err := _client.FindByOpenID(ctx)
	if err != nil {
		if errors.Is(err, mongo.ErrNoDocuments) {
			return c.Next()
		}
		return fiber.NewError(500, fmt.Sprint("读取用户错误,", err.Error()))
	}
	result := new(clientInfoResponse)
	result.SchemaToResponse(_client)
	token, err := GenerateTokenForClient(&_client.ID)
	if err != nil {
		return fiber.NewError(500, fmt.Sprint("token 生成错误,", err.Error()))
	}
	result.Token = token
	return c.JSON(serverCommon.MakeSuccessJson(result))
}

func ResponseClientBeCreated(c *fiber.Ctx) error {
	ctx, cancel := mongoDB.MongoDBTimeoutContext()
	defer cancel()
	auth := c.Locals("wxAuth").(*WxMPLoginResponse)
	_client := new(Client)
	_client.AuthInfo.WxOpenID = auth.OpenId
	_client.AuthInfo.WxUnionID = auth.UnionId
	_client.Create()
	_client.RookieOfSubject3 = true
	_client.RookieOfSubject2 = true
	err := _client.Person.Init()
	if err != nil {
		return err
	}
	_, err = _client.Save(ctx)
	if err != nil {
		return fiber.NewError(500, fmt.Sprint("创建用户错误,", err.Error()))
	}
	result := new(clientInfoResponse)
	result.SchemaToResponse(_client)
	token, err := GenerateTokenForClient(&_client.ID)
	if err != nil {
		return fiber.NewError(500, fmt.Sprint("token 生成错误,", err.Error()))
	}
	result.Token = token
	return c.JSON(serverCommon.MakeSuccessJson(result))
}
